Unreal Texture Filtration.
Algorithm.
Unreal texture filtration is very simple, in a fact it's table bilinear filtration, and it can easily be included in every inner loop.
Let's define this table:
+----------+-----------+
Y\X| even | odd |
e +----------+-----------+
v | du = .25 | du = 0 |
e | dv = .75 | dv = .50 |
n | | |
- +----------+-----------+
o | du = .50 | du = .75 |
d | dv = 0 | dv = .25 |
d | | |
+----------+-----------+
du,dv - texture correction values for U and V,
"even" - even X/Y(on screen),
"odd" - odd X/Y
Algorithm:
1. get screen X,Y (usually it exists in the inner loop)
2. looks in our table, get du,dv
3. correct texture coordinates U,V
(they must be float or fixed point, otherwise the algorithm won't work)
4. put texel on screen.
5. your code =)
6. goto 1.
Optimization.
Every coder understands that looking up every texel in a table is really slow. I found a solution while debugging my code. =) In the scanline drawing routine I carefully watched my variables du and dv. They changed like (0.25,0.75), (0.0,0.50), (0.25,0.75), (0.0,0.50),... hmm. Systematic... 0.25 goes to 0.0 and back, and 0.75 goes to 0.50 and back to 0.75. Flash! Wow! It's a simple XOR!
In a fixedpoint loop you must just XOR "start" du,dv with a constant value and add the result to U and V. "start" du,dv are taken from our table on entering the scanline loop!
Sample code.
Here's a scanline filling code with perspective correction and zbuffer (in fact it's only the part that does the filling of the remainder of affine subdivision of the scanline by 16 pixels). For U and V I use 8:8 fixedpoint.
;scanline enter
;eax - X*4
;esi - Y
ifdef filtering
shr eax,2 ;get start order
and eax,1
mov ebx,esi
and ebx,1
shl ebx,2
add ebx,eax
mov dh,byte ptr _orderTab[ebx*4] ;our table
mov dl,byte ptr _orderTab[ebx*4 + 4]
endif
mov ecx,dword ptr _Inner1Count
xor eax,eax
xor ebx,ebx
dsall66: ;inner loop
fld dword ptr _256
fdiv st(0),st(1)
fld st(0)
fmul dword ptr _Ze
fistp dword ptr _Zs ;zbuff
fld st(0) ;(1/z)/(1/z)/z/v/u...
fmul st(0),st(3)
fistp dword ptr _Vs
fmul st(0),st(3)
fistp dword ptr _Us
or ecx,ecx
jz dsall67
ZZZsm1:
mov eax,dword ptr [edi + 12345678h] ;zbuffer
mov ebx,dword ptr _Zs
add ebx,05000h
cmp eax,ebx
; jl dZl1
jb dZl1
ZZZsm2:
xor eax,eax
mov ax,word ptr _Vs
ifdef filtering
add al,dl ;add dv
adc ah,0
endif
xor ebx,ebx
shr ax,8
mov bx,word ptr _Us
ifdef filtering
add bl,dh ;add du
adc bh,0
endif
shr bx,8
add ebx,dword ptr _YTab[eax*4]
SMpt2:
mov ebx,dword ptr [ebx*4 + 12345678h]
mov dword ptr [edi],ebx
dZl1:
fld dword ptr _C.y
faddp st(1),st(0)
fld dword ptr _B.y
faddp st(2),st(0)
fld dword ptr _A.y
faddp st(3),st(0)
add edi,4
ifdef filtering
xor dx,0c0c0h ;!!!!!!!!!!!!!!!!!
endif ;adjust du and dv!
dec ecx
jmp dsall66
Happy coding.